﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using RayDen.Library.Core;
using RayDen.Library.Core.Primitives;

namespace RayDen.Library.Components.Color.Types
{

    public class RgbColor : BaseColorType<RgbColor>
    {
        public float r, g, b;
        public override RgbColor Value
        {
            get { return this; }
        }

        public RgbColor() { }

        public RgbColor(float c)
        {
            r = g = b = c;
        }

        public RgbColor(float[] c)
        {
            r = c[0];
            g = c[1];
            b = c[2];
        }

        public RgbColor(float a, float b, float c)
        {
            r = a;
            g = b;
            this.b = c;
        }

        public RgbColor(ref RgbSpectrum rgb) : this(rgb.c1, rgb.c2, rgb.c3) { }

        public RgbColor(RgbSpectrumInfo rgb, bool gamma = false)
        {
            if (gamma)
            {
                rgb.GammaCorrection();
            }
            r = rgb.c1;
            g = rgb.c2;
            this.b = rgb.c3;
        }

        public override RgbSpectrum ToXyz()
        {
            RgbSpectrum sp;
            SampledSpectrum.RGBToXYZ(r, g, b, out sp.c1, out sp.c2, out sp.c3);
            return sp;
        }

        public RgbColor FromXYZ(float x, float y, float z)
        {
            float[] rgb;
            SampledSpectrum.XYZToRGB(new[] { x, y, z }, out rgb);
            return new RgbColor(rgb[0], rgb[1], rgb[2]);
        }
        public override float Sample(float lambda)
        {
            var lmb = new[]
            {
                new Tuple<int, float>(2,SampledSpectrum.RedWavelength),                 
                new Tuple<int, float>(1, SampledSpectrum.GreenWavelength),
                new Tuple<int, float>(0,SampledSpectrum.BlueWavelength)
            };

            var lambdas = lmb.OrderBy(i => lambda - i.Item2).First();
            if (lambdas.Item1 == 0)
            {
                return b;

            }
            else if (lambdas.Item1 == 1)
            {
                return g;
            }
            else
                if (lambdas.Item1 == 2)
                {
                    return r;
                }

            return 0f;
        }
        public override bool IsBlack()
        {
            return Math.Abs(r + g + b) < MathLab.Epsilon;
        }

        public override void ToZero()
        {
            r = g = b = 0f;
        }

        public override void ToUnit()
        {
            r = g = b = 1f;
        }

        public override void TransformToRgb(out RgbSpectrum result)
        {
            result = new RgbSpectrum(r, g, b);
        }
        public override float Filter()
        {
            return new RgbSpectrumInfo(r, g, b).Filter();
        }
        protected override BaseColorType<RgbColor> Add(BaseColorType<RgbColor> v)
        {
            this.r += v.Value.r;
            this.g += v.Value.g;
            this.b += v.Value.b;
            return this;
        }

        protected override BaseColorType<RgbColor> Mul(BaseColorType<RgbColor> v)
        {
            this.r *= v.Value.r;
            this.g *= v.Value.g;
            this.b *= v.Value.b;
            return this;
        }

        protected override BaseColorType<RgbColor> AddFloat(float v)
        {
            this.r += v;
            this.g += v;
            this.b += v;
            return this;
        }

        protected override BaseColorType<RgbColor> MulFloat(float v)
        {
            this.r *= v;
            this.g *= v;
            this.b *= v;
            return this;
        }

        public override IColorType CloneValue()
        {
            return new RgbColor(r, g, b);
        }

    }
}
